//
//  TimerViewController.m
//  iosLearn
//
//  Created by 李旭阳[产品技术中心] on 2020/7/27.
//  Copyright © 2020 李旭阳[产品技术中心]. All rights reserved.
//

#import "TimerViewController.h"

@interface TimerViewController ()
@property (nonatomic, strong) NSTimer *timer;
@end

/// 参考YYTextWeakProxy的写法，写了如下的代码
/*
 NSProxy是一个专门用来做消息转发的类
 NSProxy是个抽象类，使用需自己写一个子类继承自NSProxy
 NSProxy的子类需要实现两个方法，就是上面那两个
 
 说了那么多，到底NSProxy的好处在哪呢？
 如果了解了OC中消息转发的机制，那么你肯定知道，当某个对象的方法找不到的时候，也就是最后抛出doesNotRecognizeSelector:的时候，它会经历几个步骤
 
 消息发送，从方法缓存中找方法，找不到去方法列表中找，找到了将该方法加入方法缓存，还是找不到，去父类里重复前面的步骤，如果找到底都找不到那么进入2。
 动态方法解析，看该类是否实现了resolveInstanceMethod:和resolveClassMethod:，如果实现了就解析动态添加的方法，并调用该方法，如果没有实现进入3。
 消息转发，这里分二步
 调用forwardingTargetForSelector:，看返回的对象是否为nil，如果不为nil，调用objc_msgSend传入对象和SEL。
 如果上面为nil，那么就调用methodSignatureForSelector:返回方法签名，如果方法签名不为nil，调用forwardInvocation:来执行该方法
 从上面可以看出，当继承自NSObject的对象，方法没有找到实现的时候，是需要经过第1步，第2步，第3步的操作才能抛出错误，如果在这个过程中我们做了补救措施，比如LJProxy就是在第3步的第1小步做了补救，那么就不会抛出doesNotRecognizeSelector:，程序就可以正常执行。
 但是如果是继承自NSProxy的LJWeakProxy，就会跳过前面的所有步骤，直接到第3步的第2小步，直接找到对象，执行方法，提高了性能。
 
 */
@interface LJWeakProxy : NSProxy
+ (instancetype)proxyWithTarget:(id)target;
@property (weak, nonatomic) id target;
@end
@implementation LJWeakProxy
+ (instancetype)proxyWithTarget:(id)target {
    LJWeakProxy *proxy = [LJWeakProxy alloc];
    proxy.target = target;
    return proxy;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    return [self.target methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:self.target];
}
@end

@implementation TimerViewController

//- (void)viewDidLoad {
//    [super viewDidLoad];
//
//    self.timer = [NSTimer timerWithTimeInterval:1.0 target:[LJWeakProxy proxyWithTarget:self] selector:@selector(timerRun) userInfo:nil repeats:YES];
//    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
//}

/// 这种方式虽然TimerViewController强引用timer，但是timer并没有强引用TimerViewController(由于这里的weakSelf)，因此不会出现内存泄漏的问题。
- (void)viewDidLoad {
    [super viewDidLoad];
    
    __weak typeof(self) weakSelf = self;
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        
        [weakSelf timerRun];
    }];
}

- (void)timerRun {
    NSLog(@"%s", __func__);
}

- (void)dealloc {
    [self.timer invalidate];
    NSLog(@"%s", __func__);
}

@end
